{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Day05 掌握`{}`的用法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　通过前面4天日程的学习，相信大家已经对什么是**正则表达式**，以及如何处理**完全确定**、**完全不确定**以及两者混合的模式。\n",
    "\n",
    "　　而在日常使用正则表达式完成匹配的过程中，会遇到一些对目标类型字符出现个数有限制的需求，譬如对下面的这段文字中的**行政区划**进行匹配："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-29T10:36:36.323488Z",
     "iopub.status.busy": "2020-08-29T10:36:36.323488Z",
     "iopub.status.idle": "2020-08-29T10:36:36.328475Z",
     "shell.execute_reply": "2020-08-29T10:36:36.327477Z",
     "shell.execute_reply.started": "2020-08-29T10:36:36.323488Z"
    }
   },
   "outputs": [],
   "source": [
    "s = '1 重庆市 500000 2 重庆市市辖区 500100 3 重庆市万州区 500101 4 重庆市涪陵区 500102 5 北京市东城区：110101 6 北京市西城区：110102'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　这里要匹配的**行政区划代码**和无关的**序号**都是纯数字构成，如果结合我们之前日程学习到的内容，也是可以实现匹配的，但是用到我们今天要介绍的`{}`，会简便很多。\n",
    "\n",
    "　　因为我们要匹配的是行政区划代码，通过查阅相关资料可以知晓：\n",
    "\n",
    "> 按照国务院《行政区划管理条例》规定，行政区划代码由民政部门确定、发布。该标准对我国县以上行政区划的代码做了规定，用**六位**阿拉伯数字分层次代表我国的省（自治区、直辖市）、地区（市、州、盟）、县（区、市、旗）的名称。\n",
    "\n",
    "　　所以我们如果可以构造出一种模式，限定匹配内容恰好为6个连续数字组成的片段，就可以快速地完成需求，这就需要用到**正则表达式**中的`{}`，它类似之前学习过的`*`与`+`，都是对之前的模式进行出现次数上的修饰。\n",
    "  \n",
    "　　它主要有3种使用格式，第一种`{m}`的格式，`m`是整数，代表着前面的模式出现恰好`m`次，所以我们提取**行政区划代码**的正则就可以这样写：\n",
    " "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-29T10:36:36.330469Z",
     "iopub.status.busy": "2020-08-29T10:36:36.329472Z",
     "iopub.status.idle": "2020-08-29T10:36:36.344433Z",
     "shell.execute_reply": "2020-08-29T10:36:36.343435Z",
     "shell.execute_reply.started": "2020-08-29T10:36:36.330469Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['500000', '500100', '500101', '500102', '110101', '110102']"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import re\n",
    "\n",
    "# 匹配恰好连续6位的数字\n",
    "re.findall('[0-9]{6}', s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　这样我们就非常快速地提取出所需的内容，而`{}`的第二种格式是`{m,n}`，代表着所修饰的模式最少出现`m`次，最多出现`n`次，更加的灵活，譬如下面我们匹配所有长度大于等于5且小于等于8的连续数字片段："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-29T10:36:36.346426Z",
     "iopub.status.busy": "2020-08-29T10:36:36.345429Z",
     "iopub.status.idle": "2020-08-29T10:36:36.352410Z",
     "shell.execute_reply": "2020-08-29T10:36:36.351413Z",
     "shell.execute_reply.started": "2020-08-29T10:36:36.345429Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['123456', '1234567']"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = 'A:123456 B:1234 C:1234567 D:12'\n",
    "\n",
    "re.findall('[0-9]{5,8}', s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　第三种格式是`{m,}`，即`n`可以空着不写，这样代表匹配连续出现`m`次及以上："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-29T10:36:36.354406Z",
     "iopub.status.busy": "2020-08-29T10:36:36.353412Z",
     "iopub.status.idle": "2020-08-29T10:36:36.361387Z",
     "shell.execute_reply": "2020-08-29T10:36:36.360391Z",
     "shell.execute_reply.started": "2020-08-29T10:36:36.354406Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['123456', '1234', '1234567']"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = 'A:123456 B:1234 C:1234567 D:12'\n",
    "\n",
    "# 匹配所有出现次数3次及以上的连续数字\n",
    "re.findall('[0-9]{3,}', s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Day05 课后小测验\n",
    "\n",
    "　　相信通过上面的内容，你已经对`{}`的用法有了一定了解，趁热打铁，下面请你从下面的字符串中提取所有长度在**3到8**之间的**大写字母开头**的单词："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-29T10:36:36.363383Z",
     "iopub.status.busy": "2020-08-29T10:36:36.362384Z",
     "iopub.status.idle": "2020-08-29T10:36:36.367371Z",
     "shell.execute_reply": "2020-08-29T10:36:36.366402Z",
     "shell.execute_reply.started": "2020-08-29T10:36:36.363383Z"
    }
   },
   "outputs": [],
   "source": [
    "target = 'The phrase Regular expressions, also Called regexes, is often used to mean the Specific, standard Textual syntax for Representing Patterns for matching text, as Distinct from the Mathematical notation Described below. '"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 提示：在使用{m,n}方式提取目标字符的时候正则表达式会误把长度超过n的单词的前n位**截断**下来当成满足要求的结果，譬如下面这样："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-29T10:36:36.369401Z",
     "iopub.status.busy": "2020-08-29T10:36:36.368367Z",
     "iopub.status.idle": "2020-08-29T10:36:36.376347Z",
     "shell.execute_reply": "2020-08-29T10:36:36.375349Z",
     "shell.execute_reply.started": "2020-08-29T10:36:36.369401Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['aaaaa', 'bbbbb', 'cccc']"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 提取长度在3到5之间的单词\n",
    "re.findall('[a-z]{3,5}', 'aaaaaa bbbbbb cccc')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　但这显然不是我们的目标，因此你可以结合`Python`中的其他知识点譬如**列表推导**来配合正则表达式完成任务："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-29T10:36:36.377344Z",
     "iopub.status.busy": "2020-08-29T10:36:36.377344Z",
     "iopub.status.idle": "2020-08-29T10:36:36.386320Z",
     "shell.execute_reply": "2020-08-29T10:36:36.385323Z",
     "shell.execute_reply.started": "2020-08-29T10:36:36.377344Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['cccc']"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 利用列表推导\n",
    "# 提取长度在3到5之间的单词\n",
    "[word for word in re.findall('[a-z]{3,}', 'aaaaaa bbbbbb cccc') if len(word) <= 5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['The', 'Regular', 'Called', 'Specific', 'Textual', 'Patterns', 'Distinct']"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[word for word in re.findall('[A-Z]{1}[a-z]{2,}',target) if len(word)<=8]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-26T12:55:19.898241Z",
     "iopub.status.busy": "2020-08-26T12:55:19.897245Z",
     "iopub.status.idle": "2020-08-26T12:55:19.904225Z",
     "shell.execute_reply": "2020-08-26T12:55:19.903227Z",
     "shell.execute_reply.started": "2020-08-26T12:55:19.898241Z"
    }
   },
   "source": [
    "　　请将你的答案截图发到本帖评论区~"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {},
    "version_major": 2,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
